import java.util.Iterator;
import java.util.Vector;

public class World implements Runnable {
	private Vector<ExternalForce> externalForces;
	private Vector<Mass> masses;
	private Thread asThread;
	private double dt;
	
	public World(double dt) {
		this.dt = dt;
		
		externalForces = new Vector<ExternalForce>();
		masses = new Vector<Mass>();
	}
	
	public void addMass(Mass m) {
		masses.add(m);
	}
	
	public void removeMass(Mass m) {
		masses.remove(m);
	}
	
	public void addExternalForce(ExternalForce ef) {
		externalForces.add(ef);
	}
	
	public void removeExternalForce(ExternalForce ef) {
		externalForces.remove(ef);
	}
	
	public Vector<Mass> getMasses() {
		return masses;
	}
	
	public void startSimulation() {
		if (asThread == null) {
			asThread = new Thread(this);
			asThread.start();
		}
	}
	
	public void stopSimulation() {
		if (asThread != null)
			asThread = null;
	}
	
	public void run() {
		
		while (asThread != null) {
			// Updates external forces
			for (Iterator<ExternalForce> ef = externalForces.iterator(); ef.hasNext(); )
				if (!ef.next().update(dt))
					ef.remove();
			
			
			// Calculates external forces and updates masses
			Point3D ef;
			for (Mass m : masses) {
				ef = new Point3D(0.0, 0.0, 0.0);
				
				for (ExternalForce f : externalForces)
					ef = ef.sum(f.value(m));
				
				m.updateForce(ef, dt);
			}
			
			// Integration
			for (Mass m : masses)
				m.integrate(dt);
		}
	}
}
